<!doctype html>
<html lang="en">

	<head>
		<meta charset="utf-8">
		<title>promise demo</title>
		<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
	</head>

	<body>
		<div id="myPanel">
			<img data-src="../img/2.png" />
			<img data-src="../img/2.png" />
			<img data-src="../img/2.png" />
			<img data-src="../img/2.png" />
		</div>
		<button id="myButton">点击</button>
		<script type="text/javascript">
			$.createCache = function(requestFunction) {
				var cache = {};
				return function(key, callback) {
					if(!cache[key]) {
						cache[key] = $.Deferred(function(defer) {
							requestFunction(defer, key);
						}).promise();
					}
					return cache[key].done(callback);
				};
			}

			$.loadImage = $.createCache(function(defer, url) {
				var image = new Image();

				function cleanUp() {
					image.onload = image.onerror = null;
				}
				defer.then(cleanUp, cleanUp);
				image.onload = function() {
					defer.resolve(url);
				};
				image.onerror = defer.reject;
				image.src = url;
			});

			$.fn.bindOnce = function(event, callback) {
				debugger
				var element = $(this[0]),
					defer = element.data("bind_once_defer_" + event);
				if(!defer) {
					defer = $.Deferred();

					function deferCallback() {
						element.unbind(event, deferCallback);
						defer.resolveWith(this, arguments);
					}
					element.bind(event, deferCallback)
					element.data("bind_once_defer_" + event, defer);
				}
				return defer.done(callback).promise();
			};

			$.fn.firstClick = function(callback) {
				return this.bindOnce("click", callback);
			};

			$("#myButton").firstClick(function() {
				debugger
				var panel = $("#myPanel"),
					promises = [];
				$("img", panel).each(function() {
					var image = $(this),
						src = image.attr("data-src");
					if(src) {
						promises.push(
							$.loadImage(src).then(function() {
								image.attr("src", src);
							}, function() {
								image.attr("src", "error.png");
							})
						);
					}
				});

				promises.push(panel.slideDownPromise());

				$.when.apply(null, promises).done(function() {
					panel.fadeIn();
				});
			});
		</script>

	</body>

</html>